package threadPool;

import java.util.Scanner;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;

public class StuThreadPoolExecutor {
    public static void main(String[] args) {
        /*
        *① CorePoolSize
        *线程的核心线程数。默认情况下，核心线程数会在线程中一直存活，即使它们处于闲置状态。
        *如果将ThreadPoolExecutor的allowCoreThreadTimeOut属性设置为true，那么核心线程就会存在超时策略，这个时间间隔有keepAliveTime所决定，
        *当等待时间超过keepAliveTime所指定的时长后，核心线程就会被停止。
        */
        final int corePoolSize=6;
        /*
        * ② maximumPoolSize
        * 线程池所能容纳的最大线程数。当活动线程数达到这个数值后，后续的新任务将会被阻塞。
        * */
        final int maximumPoolSize=10;
        /*
        * ③ keepAliveTime
        *非核心线程闲置时的超时时长，超过这个时长，非核心线程就会被回收，
        *当ThreadPoolExector的allowCoreThreadTimeOut属性设置为True时，keepAliveTime同样会作用于核心线程。
        * */
        final int keepAliveTime=1000;
        /*
        * ④ unit
        *用于指定keepAliveTime参数的时间单位，这是一个枚举，常用的有TimeUnit.MILLISECONDS（毫秒）、
        *TimeUnit.SECONDS(秒)以及TimeUnit.MINUTES(分钟)等。
        * */
        final TimeUnit timeUnit = TimeUnit.SECONDS;
        /*
        * ⑤ workQueue
        *线程池中的任务队列，通过线程池execute方法提交的Runnable对象会存储在这个参数中。这个任务队列是BlockQueue类型，属于阻塞队列，
        * 就是当队列为空的时候，此时取出任务的操作会被阻塞，等待任务加入队列中不为空的时候，才能进行取出操作，而在满队列的时候，添加操作同样被阻塞。
        * */

        final LinkedBlockingQueue<Runnable>taskQueue=new LinkedBlockingQueue<>(30);//设置最大容量
        /*
        *⑥ threadFactory
        *线程工厂，为线程池提供创建新线程的功能。ThreadFactory是一个接口，它只有一个方法，newThread（Runnable r），用来创建线程。
        * */
        final ThreadFactory threadFactory = Executors.defaultThreadFactory();
        /*
        * ⑦ 饱和策略(拒绝策略),当任务队列和线程池都满了时所采取的应对策略，有已下几种：
        *AbordPolicy: 抛出RejectedExecutionExcepton异常，该策略是默认策略。
        *CallerRunsPolicy: 用调用者所在的线程来处理任务。此策略提供简单的反馈控制，能够减缓新任务提交速度。
        *DiscardPolicy: 直接将该任务舍弃。
        *DiscardOldestPolicy: 丢弃最老的任务，并执行当前任务。
        * */
        final ThreadPoolExecutor.CallerRunsPolicy policy=new ThreadPoolExecutor.CallerRunsPolicy();
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(corePoolSize,maximumPoolSize,keepAliveTime
                ,timeUnit,taskQueue,threadFactory,policy);


        final Integer[] num = {1};
        Semaphore semaphore = new Semaphore(1);
        for (final int[] i = {0}; i[0] < 1000; i[0]++) {
            threadPoolExecutor.execute(new Runnable() {
                @Override
                public void run() {
                    try {
                        semaphore.acquire();
                        System.out.println(num[0]++);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }finally {
                        semaphore.release();
                    }
                }
            });
        }
    }
}
